/**
 * Computer Graphics Lecture WS 2009/2010 Ulm University
 * Creator: Manuel Finckh
 * Email:   manuel.finckh@uni-ulm.de
 */

#ifndef SCENE_H
#define SCENE_H

#include "material.h"
#include "cam.h"
#include "rtStructs.h"
#include <iostream>
#include "tools/loadHDR.h"

struct Scene {
  Triangle * triangles;
  Vec3 * normals;
  Vec2 * uv;
  int num_tris;
  int ResX, ResY;

  Material * material;
  int num_material;
  int * mat_index;
  
  Light * lights;
  int num_lights;
  
  float * light_pdf;

  Vec3 * environment;
  int env_x, env_y;
  float * ee;

  Cam * cam;

  Scene(const char * file);
  Scene(const char * file, int rx, int ry);
  ~Scene();

  bool LoadSrs(const char * file);
  bool LoadRa2(const char * file);

  Vec3 getShadingNormal(const Ray &ray, const int tri_id) const;
  Vec3 getEnvironment(const Vec3 &d) const;
  void loadEnvironment(char *filename);
  
  Vec3 sampleRandomLight(int &id, float r0, float r1, float r2); // returns a random point on a random light source
  
};

inline Vec3 Scene::getShadingNormal(const Ray &ray, const int tri_id) const {
  float alpha, beta, gamma;
  triangles[tri_id].getBarycentric(ray, alpha, beta); gamma = 1.0f - alpha - beta;
  Vec3 n = gamma * normals[tri_id*3] + alpha * normals[tri_id*3+1] + beta * normals[tri_id*3+2];
  n.normalize();
  return n;
}


inline Vec3 Scene::getEnvironment(const Vec3 &d) const {
	//float r=(1.0/M_PI)*acos(d.z)/sqrt(d.x*d.x + d.y*d.y);
	
	// drehung des vektors um 90 grad!!!!!
	Vec3 rot(0.0);
	rot.x = d.x;
	rot.y = d.z;
	rot.z = d.y;
	
	
   float u = 1 + atan2(rot.x,-rot.z) / M_PI;
   float v = acos(rot.y) / M_PI;
   //std::cout<<u<<" , "<<v<<std::endl;
   //float u = d.x * r;
   //float v = d.y*r;
   u = (u+1.0) / 2.0;
   //v = (v+1.0) / 2.0;
   u *= env_x;
   v *= env_y;
   Vec3 tmp = environment[(int)v*env_x + (int)u];
   return tmp;
   /*
   int x_low = floor(u);
  int y_low = floor(v);
  int x_high = ceil(u);
  int y_high = ceil(v);
  float alpha = u - x_low;
  float beta = v - y_low;
  //std::cout<<x_low<<" "<<y_low<<" "<<x_high<<" "<<y_high<<" "<<std::endl;
  Vec3 x1 = alpha * environment[y_low*env_x + x_low] + (1-alpha) * environment[y_low*env_x + x_high]; 
  Vec3 x2 = alpha * environment[y_high*env_x + x_low] + (1-alpha) * environment[y_high*env_x + x_high];
  
  return (beta * x1 + (1.0-beta) * x2);
  */
  //return Vec3(0.0f);
}

#endif

